home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / snip9503 / getopts.c < prev    next >
C/C++ Source or Header  |  1995-03-14  |  7KB  |  201 lines

  1. /*
  2. **  GETOPTS.C - Universal command line options parser
  3. **
  4. **  Original Copyright 1993 by Bob Stout as part of
  5. **  the MicroFirm Function Library (MFL)
  6. **
  7. **  This subset version is hereby donated to the public domain.
  8. */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "portable.h"
  14. #include "getopts.h"
  15.  
  16. #define NUL '\0'
  17. #define MAX_XARGS 512
  18.  
  19. int   xargc;
  20. char *xargv[MAX_XARGS];
  21.  
  22. /*
  23. **  getopts()
  24. **
  25. **  Parameters: 1 - argc from main()
  26. **              2 - argv from main()
  27. **              3 - your program's options[] array
  28. **
  29. **  Returns: Number of options specified or -1 if error
  30. **
  31. **  Note: Your program should declare the global options[] array which
  32. **        specifies all options recognized by getopts().
  33. */
  34.  
  35. int getopts(int argc, char *argv[])
  36. {
  37.       int i, count, argidx = 0;
  38.       char *argp;
  39.       struct Option_Tag *ptr;
  40.  
  41.       xargc = argc;
  42.       xargv[argidx++] = argv[0];
  43.       for (i = 1, count = 0; i < argc; ++i)
  44.       {
  45.             if (strchr("-/", argv[i][0]) && !strchr("-/", argv[i][1]))
  46.             {
  47.                   Boolean_T found_it = FALSE;
  48.  
  49.                   /*
  50.                   ** Found a switch - If the 2nd character is also a switch
  51.                   ** character. If so, then it's a literal and is skipped
  52.                   */
  53.  
  54.                   if (strchr("-/", argv[i][1]))
  55.                         continue;
  56.  
  57.                   for (ptr = options; ptr->buf; ++ptr)
  58.                   {
  59.                         if ((int)argv[i][1] == ptr->letter) switch (ptr->type)
  60.                         {
  61.                         case Boolean_Tag:
  62.                               if ('-' == argv[i][2])
  63.                                     *((Boolean_T *)(ptr->buf)) = FALSE;
  64.                               else  *((Boolean_T *)(ptr->buf)) = TRUE;
  65.                               ++count;
  66.                               --xargc;
  67.                               found_it = TRUE;
  68.                               break;
  69.  
  70.                         case Word_Tag:
  71.                               sscanf(&argv[i][2], "%hd", (short *)(ptr->buf));
  72.                               ++count;
  73.                               --xargc;
  74.                               found_it = TRUE;
  75.                               break;
  76.  
  77.                         case DWord_Tag:
  78.                               sscanf(&argv[i][2], "%ld", (long *)(ptr->buf));
  79.                               ++count;
  80.                               --xargc;
  81.                               found_it = TRUE;
  82.                               break;
  83.  
  84.                         case Double_Tag:
  85.                               sscanf(&argv[i][2], "%lg",(double *)(ptr->buf));
  86.                               ++count;
  87.                               --xargc;
  88.                               found_it = TRUE;
  89.                               break;
  90.  
  91.                         case String_Tag:
  92.                               strcpy(ptr->buf, &argv[i][2]);
  93.                               ++count;
  94.                               --xargc;
  95.                               found_it = TRUE;
  96.                               break;
  97.  
  98.                         default:
  99.                               return ERROR;
  100.                         }
  101.                   }
  102.                   if (!found_it)
  103.                         return ERROR;
  104.             }
  105.             else                          /* It must be a file name     */
  106.             {
  107.                   DOSFileData ffblk;
  108.  
  109.                   /* Set argp to point to the filename                  */
  110.  
  111.                   if (strchr("-/", argv[i][0]))
  112.                         argp = &argv[i][1];
  113.                   else  argp =  argv[i];
  114.  
  115.                   /* If no wildcards, just copy it */
  116.  
  117.                   if (!strchr(argp, '*') && !strchr(argp, '?'))
  118.                   {
  119.                         xargv[argidx++] = argp;
  120.                         continue;
  121.                   }
  122.  
  123.                   /* Expand wildcards, if possible                      */
  124.  
  125.                   if (0 == FIND_FIRST(argp, 0xff, &ffblk))
  126.                   {
  127.                         char path[FILENAME_MAX], *p;
  128.  
  129.                         /* Save the path for re-attachment              */
  130.  
  131.                         if (NULL == (p = strrchr(argp, '\\')))
  132.                               p = strrchr(argp, '/');
  133.                         if (p)
  134.                         {
  135.                               char ch = *p;
  136.  
  137.                               *p = NUL;
  138.                               strcat(strcpy(path, argp), "\\");
  139.                               *p = ch;
  140.                         }
  141.                         else  *path = NUL;
  142.                         --xargc;
  143.                         do
  144.                         {                             
  145.                               xargv[argidx] = malloc(strlen(ffblk.name)
  146.                                     + strlen(path) + 2);
  147.                               strcat(strcpy(xargv[argidx], path), ffblk.name);
  148.                               ++argidx;
  149.                               ++xargc;
  150.                         
  151.                         } while (0 == FIND_NEXT(&ffblk));
  152.                   }
  153.             }
  154.       }
  155.       return count;
  156. }
  157.  
  158. #ifdef TEST
  159.  
  160. #include <stdlib.h>
  161.  
  162. Boolean_T test1 = TRUE, test2 = FALSE;
  163. int   test3     = -37;
  164. long  test4     = 100000L;
  165. char  test5[80] = "Default string";
  166.  
  167. struct Option_Tag options[] = {
  168.       {'A',  Boolean_Tag, &test1 },             /* Valid options        */
  169.       {'B',  Boolean_Tag, &test2 },
  170.       {'C',  Word_Tag,    &test3 },
  171.       {'D',  DWord_Tag,   &test4 },
  172.       {'E',  String_Tag,   test5 },
  173.       {'\0', ERROR,        NULL  }              /* Terminating record   */
  174. };
  175.  
  176. #define TFprint(v) ((v) ? "TRUE" : "FALSE")
  177.  
  178. int main(int argc, char *argv[])
  179. {
  180.       int i;
  181.  
  182.       printf("Defaults:\ntest1 = %s\ntest2 = %s\ntest3 = %d\ntest4 = %ld\n"
  183.             "test5 = \"%s\"\n\n", TFprint(test1), TFprint(test2), test3,
  184.             test4, test5);
  185.  
  186.       printf("getopts() returned %d\n", getopts(argc, argv));
  187.  
  188.       printf("Options are now:\ntest1 = %s\ntest2 = %s\ntest3 = %d\n"
  189.             "test4 = %ld\ntest5 = \"%s\"\n\n", TFprint(test1),
  190.             TFprint(test2), test3, test4, test5);
  191.  
  192.       puts("Hit any key to continue");
  193.       getch();
  194.       for (i = 0; i < xargc; ++i)
  195.             printf("xargv[%d] = \"%s\"\n", i, xargv[i]);
  196.       printf("\nxargc = %d\n", xargc);
  197.       return 0;
  198. }
  199.  
  200. #endif
  201.